package com.core.code;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.net.URL;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.core.controller.BaseController;
import com.core.plugin.bind.Route;
import com.google.common.collect.Maps;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.DbKit;

import freemarker.template.Configuration;
import freemarker.template.Template;
/**
 * 代码生成器
 */
@Route(controllerKey="/code",viewPath="/pages/code")
public class CodeController extends BaseController<TableInfo> {
	
	/**
	 * 数据库表
	 */
	public void index() {
		List<TableInfo> tableList = new ArrayList<TableInfo>();
		try {
			ResultSet rstTable = getDbMetaData().getTables(null, null, null,new String[] { "TABLE" });
	        ResultSetMetaData rsmd = rstTable.getMetaData();
	        
	        int i = rsmd.getColumnCount();
	        for(int j = 1; j <= i; j++) {
	            System.out.println(rsmd.getColumnName(j));
	        }
	        
            while (true) {
                try {
                	rstTable.next();
                	TableInfo tableInfo = new TableInfo();
                    tableInfo.setComments(rstTable.getString("REMARKS"));
                    tableInfo.setTableName(rstTable.getString("TABLE_NAME"));
                    tableList.add(tableInfo);
                } catch (Exception e) {
                    break;
                }
            }
		} catch (SQLException e) {
			e.printStackTrace();
		}
		Map<String,Object> map = Maps.newHashMap();
		map.put("rows", tableList);
		map.put("total", tableList.size());
		map.put("page", 1);
		renderJson(map);
	}
	
	/**
	 * 生成代码
	 */
	public void genCode() throws Exception {
		String packagePath = getPara("packagePath");
		String tableNames = getPara("tableNames");
		
		String genController ="1"; //getPara("genController");
		String genValidator ="1"; // getPara("genValidator");
		String genInterceptor ="1"; // getPara("genInterceptor");
		String genEntity ="1"; // getPara("genEntity");
		String genList ="1"; // getPara("genList");
		String genAdd ="1"; // getPara("genAdd");
		String genUpdate ="1"; // getPara("genUpdate");
		
		Configuration cfg = new Configuration();
		cfg.setDefaultEncoding("utf-8");
		URL url = this.getClass().getResource("");
		String fileName = url.getFile();
		cfg.setDirectoryForTemplateLoading(new File(fileName));
		
		String[] tables = tableNames.split(",");
		for (String tableName : tables) {
			String className = tableToClass(tableName);
			Map<String,Object> fields = new HashMap<String,Object>();
			fields.put("className",className);
			fields.put("packagePath", packagePath);
			fields.put("tableName", tableName);
			fields.put("columnList", getColumnInfoByTableName(tableName));
			fields.put("columnStr", getColumnStrInfoByTableName(tableName));
			String basePath = "";
			String osname = System.getProperty("os.name");
			if (osname.startsWith("win") || osname.startsWith("Win")) {
				basePath = "d:/temp/src/" + packagePath.replaceAll("\\.", "/");
			} else {
				basePath = "/home/temp/src/" + packagePath.replaceAll("\\.", "/");
			}
			if (StrKit.notBlank(genController)) {
				genFile(cfg, "controller.ftl", fields, basePath + "/controller", className + "Controller.java");
			}
			if (StrKit.notBlank(genValidator)) {
				genFile(cfg, "validator.ftl", fields, basePath + "/validator", className + "Validator.java");
			}
			if (StrKit.notBlank(genInterceptor)) {
				genFile(cfg, "interceptor.ftl", fields, basePath + "/interceptor", className + "Interceptor.java");
			}
			if (StrKit.notBlank(genEntity)) {
				genFile(cfg, "entity.ftl", fields, basePath + "/entity", className + ".java");
			}
			if (StrKit.notBlank(genList)) {
				genFile(cfg, "list.ftl", fields, basePath + "/pages/"+tableName, tableName + "List.jsp");
			}
			if (StrKit.notBlank(genAdd)) {
				genFile(cfg, "add.ftl", fields, basePath + "/pages/"+tableName, tableName + "Add.jsp");
			}
			if (StrKit.notBlank(genUpdate)) {
				genFile(cfg, "update.ftl", fields, basePath + "/pages/"+tableName, tableName + "Update.jsp");
			}
		}
		renderNull();
	}
	
	/**
	 * 生成文件
	 */
	public void genFile(Configuration cft, String templateName, Map<String,Object> fields,String filePath, String fileName) {
        File fPath = new File(filePath);
        if (!fPath.exists()) {
            fPath.mkdirs();
        }
        File outputFile = new File(fPath, fileName);
        try {
            Writer writer = new FileWriter(outputFile);
            Template temp = cft.getTemplate(templateName);
            temp.process(fields, writer);
            writer.flush();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
	
	/**
	 * 表名转换为类名
	 */
	public String tableToClass(String tableName) {
		if (StrKit.notBlank(tableName)) 
			tableName = StrKit.firstCharToUpperCase(tableName);
		return tableName;
	}
	
	/**
	 * 根据表名获取列
	 */
	public String getColumnStrInfoByTableName(String tableName){
		List<ColumnInfo> list = getColumnInfoByTableName(tableName);
		StringBuilder sb = new StringBuilder();
		for (ColumnInfo columnInfo : list) {
			sb.append(columnInfo.getColumnName()).append("(").append(columnInfo.getJavaType()).append(")").append("\n\r");
		}
		return sb.toString();
	}
	
	/**
	 * 根据表名获取列
	 */
	public List<ColumnInfo> getColumnInfoByTableName(String tableName){
		List<ColumnInfo> list = new ArrayList<ColumnInfo>();
		if (StrKit.notBlank(tableName)) {
			try {
				ResultSet rst = getDbMetaData().getColumns(null, null,tableName, null);
				while (true) {
					try {
						rst.next();
						ColumnInfo ci = new ColumnInfo();
						ci.setColumnName(rst.getString("COLUMN_NAME"));
						ci.setComments(rst.getString("REMARKS"));
						ci.setDataType(rst.getString("TYPE_NAME"));
						ci.setDataPrecision(rst.getInt("COLUMN_SIZE"));
						ci.setDataScale(rst.getInt("DECIMAL_DIGITS"));
						list.add(ci);
						if(rst.isLast()){
							break;
						}
					} catch (Exception e) {
						break;
					}
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
        return list;
    }

	private DatabaseMetaData getDbMetaData() {
		try {
			Connection con = DbKit.getConfig().getConnection();
			return con.getMetaData();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null ;
	}
}
